home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / slip.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  8KB  |  400 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "ax25.h"
  10. #include "slip.h"
  11. #include "asy.h"
  12. #include "trace.h"
  13. #if defined(MODEM_CALL)
  14. #include <string.h>
  15. #include "timer.h"
  16. #endif
  17.  
  18. extern unsigned restricted_dev;
  19. int asy_ioctl();
  20. int kiss_ioctl();
  21. int slip_send();
  22. void doslip();
  23. int asy_output();
  24.  
  25. /* Slip level control structure */
  26. struct slip slip[ASY_MAX];
  27.  
  28. /* Send routine for point-to-point slip
  29.  * This is a trivial function since there is no slip link-level header
  30.  */
  31. /*ARGSUSED*/
  32. int
  33. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  34. struct mbuf *data;        /* Buffer to send */
  35. struct interface *interface;    /* Pointer to interface control block */
  36. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  37. char precedence;
  38. char delay;
  39. char throughput;
  40. char reliability;
  41. {
  42.     if(interface == NULLIF){
  43.         free_p(data);
  44.         return -1;
  45.     }
  46.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  47.     return (*interface->raw)(interface,data);
  48. }
  49. /* Send a raw slip frame -- also trivial */
  50. int
  51. slip_raw(interface,data)
  52. struct interface *interface;
  53. struct mbuf *data;
  54. {
  55.     /* Queue a frame on the slip output queue and start transmitter */
  56.     return slipq(interface->dev,data);
  57. }
  58. /* Encode a raw packet in slip framing, put on link output queue, and kick
  59.  * transmitter
  60.  */
  61. static int
  62. slipq(dev,data)
  63. int16 dev;        /* Serial line number */
  64. struct mbuf *data;    /* Buffer to be sent */
  65. {
  66.     register struct slip *sp;
  67.     struct mbuf *slip_encode(),*bp;
  68.     void asy_start();
  69.  
  70.     if((bp = slip_encode(data)) == NULLBUF)
  71.         return -1;    
  72.  
  73.     sp = &slip[dev];
  74.     enqueue(&sp->sndq,bp);
  75.     sp->sndcnt++;
  76.     if(sp->tbp == NULLBUF)
  77.         asy_start(dev);
  78.     return 0;
  79. }
  80. /* Start output, if possible, on asynch device dev */
  81. static void
  82. asy_start(dev)
  83. int16 dev;
  84. {
  85.     register struct slip *sp;
  86.  
  87.     if(!stxrdy(dev))
  88.         return;        /* Transmitter not ready */
  89.  
  90.     sp = &slip[dev];
  91.     if(sp->tbp != NULLBUF){
  92.         /* transmission just completed */
  93.         free_p(sp->tbp);
  94.         sp->tbp = NULLBUF;
  95.     }
  96.     if(sp->sndq == NULLBUF)
  97.         return;    /* No work */
  98.  
  99.     sp->tbp = dequeue(&sp->sndq);
  100.     sp->sndcnt--;
  101.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  102. }
  103. /* Encode a packet in SLIP format */
  104. static
  105. struct mbuf *
  106. slip_encode(bp)
  107. struct mbuf *bp;
  108. {
  109.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  110.     register char *cp;
  111.     char c;
  112.  
  113.     /* Allocate output mbuf that's twice as long as the packet.
  114.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  115.      */
  116.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  117.     if(lbp == NULLBUF){
  118.         /* No space; drop */
  119.         free_p(bp);
  120.         return NULLBUF;
  121.     }
  122.     cp = lbp->data;
  123.  
  124.     /* Flush out any line garbage */
  125.     *cp++ = FR_END;
  126.  
  127.     /* Copy input to output, escaping special characters */
  128.     while(pullup(&bp,&c,1) == 1){
  129.         switch(uchar(c)){
  130.         case FR_ESC:
  131.             *cp++ = FR_ESC;
  132.             *cp++ = T_FR_ESC;
  133.             break;
  134.         case FR_END:
  135.             *cp++ = FR_ESC;
  136.             *cp++ = T_FR_END;
  137.             break;
  138.         default:
  139.             *cp++ = c;
  140.         }
  141.     }
  142.     *cp++ = FR_END;
  143.     lbp->cnt = cp - lbp->data;
  144.     return lbp;
  145. }
  146. /* Process incoming bytes in SLIP format
  147.  * When a buffer is complete, return it; otherwise NULLBUF
  148.  */
  149. static
  150. struct mbuf *
  151. slip_decode(dev,c)
  152. int16 dev;    /* Slip unit number */
  153. char c;        /* Incoming character */
  154. {
  155.     struct mbuf *bp;
  156.     register struct slip *sp;
  157.  
  158.     sp = &slip[dev];
  159.     switch(uchar(c)){
  160.     case FR_END:
  161.         bp = sp->rbp;
  162.         sp->rbp = NULLBUF;
  163.         sp->rcnt = 0;
  164.         return bp;    /* Will be NULLBUF if empty frame */
  165.     case FR_ESC:
  166.         sp->escaped = 1;
  167.         return NULLBUF;
  168.     }
  169.     if(sp->escaped){
  170.         /* Translate 2-char escape sequence back to original char */
  171.         sp->escaped = 0;
  172.         switch(uchar(c)){
  173.         case T_FR_ESC:
  174.             c = FR_ESC;
  175.             break;
  176.         case T_FR_END:
  177.             c = FR_END;
  178.             break;
  179.         default:
  180.             sp->errors++;
  181.             break;
  182.         }
  183.     }
  184.     /* We reach here with a character for the buffer;
  185.      * make sure there's space for it
  186.      */
  187.     if(sp->rbp == NULLBUF){
  188.         /* Allocate first mbuf for new packet */
  189.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  190.             return NULLBUF; /* No memory, drop */
  191.         sp->rcp = sp->rbp->data;
  192.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  193.         /* Current mbuf is full; link in another */
  194.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  195.             /* No memory, drop whole thing */
  196.             free_p(sp->rbp);
  197.             sp->rbp = NULLBUF;
  198.             sp->rcnt = 0;
  199.             return NULLBUF;
  200.         }
  201.         sp->rbp1 = sp->rbp1->next;
  202.         sp->rcp = sp->rbp1->data;
  203.     }
  204.     /* Store the character, increment fragment and total
  205.      * byte counts
  206.      */
  207.     *sp->rcp++ = c;
  208.     sp->rbp1->cnt++;
  209.     sp->rcnt++;
  210.     return NULLBUF;
  211. }
  212. /* Process SLIP line I/O */
  213. void
  214. doslip(interface)
  215. struct interface *interface;
  216. {
  217.     char c;
  218.     struct mbuf *bp;
  219.     int16 dev;
  220.     int16 asy_recv();
  221.  
  222.     dev = interface->dev;
  223.     if(dev == restricted_dev) return;
  224.     /* Process any pending input */
  225.     while(asy_recv(dev,&c,1) != 0)
  226.         if((bp = slip_decode(dev,c)) != NULLBUF)
  227.             (*slip[dev].recv)(interface,bp);
  228.  
  229.     /* Kick the transmitter if it's idle */
  230.     if(stxrdy(dev))
  231.         asy_start(dev);
  232. }
  233. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  234.  * link level header
  235.  */
  236. void
  237. slip_recv(interface,bp)
  238. struct interface *interface;
  239. struct mbuf *bp;
  240. {
  241.     int ip_route();
  242.  
  243.     /* By definition, all incoming packets are "addressed" to us */
  244.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  245.     ip_route(bp,0);
  246. }
  247.  
  248. #if defined(MODEM_CALL)
  249.  
  250. void check_time(),keep_things_going();
  251.  
  252. static char *ex="r\015t\011s n\012E\004b\010\\\\N\000";
  253. static struct timer ar;
  254. static int debug;
  255.  
  256. static
  257. int m_send(dev, a)
  258. unsigned dev;
  259. char *a;
  260. {
  261.     unsigned l;
  262.     char *ss, *cp, *pt;
  263.  
  264.     ss=pt=a;
  265.     l=0;
  266.     while(*a) {
  267.         if(*a=='\\') {
  268.             a++;
  269.             if(*a=='d') {
  270.                 asy_output(dev,ss,l);
  271.                 l=0;
  272.                 a++;
  273.                 ss=pt=a;
  274.                 set_timer(&ar,1000);
  275.                 start_timer(&ar);
  276.                     while(ar.state == TIMER_RUN)
  277.                     keep_things_going();
  278.                 continue;
  279.             }
  280.             if((cp = strchr(ex,*a)) != NULL) {
  281.                 *pt++ = *(cp+1);
  282.                 l++;
  283.                 a++;
  284.                 continue;
  285.             }
  286.         } /* if(*a=='\\') */
  287.         *pt++ = *a++;
  288.         l++;
  289.     }
  290.     asy_output(dev,ss,l);
  291. } /* m_send */
  292.  
  293. /******************************************************************************
  294.  * returns the character position of the substring pat within the string
  295.  *  src if the substring exists, 0 if the substring does not exist.
  296.  *  the first character position is considered to be 1, not 0 which
  297.  *  is the first position within the array.
  298.  */
  299. static
  300. int xinstr(src,pat)
  301. char *src,*pat;
  302. {
  303.     register char *s_src, *s_pat;
  304.     int rtn;
  305.  
  306.     s_src=src;
  307.     s_pat=pat;
  308.     rtn=1;
  309.     while(*s_src) {
  310.         while((*s_pat) && (*s_src==*s_pat)) { s_src++; s_pat++; }
  311.         if(!(*s_pat)) return(rtn);
  312.         rtn++; s_pat=pat; s_src=(++src);
  313.     }
  314.     return(0);
  315. } /* xinstr */
  316.  
  317. static
  318. int m_expect(dev, a)
  319. unsigned dev;
  320. char *a;
  321. {
  322.     char *str, *pstr, c;
  323.     int tot;
  324.  
  325.     if(*a=='\\') return 1;
  326. /*
  327.  * make room for the received string
  328.  */
  329.         if((str=malloc(5000)) == NULL) {
  330.         printf("No room for malloc: m_expect\n");
  331.         fflush(stdout);
  332.         return -1;
  333.     }
  334. /*
  335.  * a single backspace means don't wait for anything
  336.  */
  337.     pstr=str;
  338.     *pstr='\0';
  339.     tot=0;
  340.     set_timer(&ar,30000);
  341.     start_timer(&ar);
  342.     while (!xinstr(str,a)) {
  343.         while(asy_recv(dev,&c,1)) { 
  344. /*
  345.  * ignore incoming nulls
  346.  */
  347.             if(c) {
  348.                 *(pstr++)=c;
  349.                 *pstr='\0';
  350.                 if(++tot > 4995) {
  351.                     if(debug) printf("%s",str);fflush(stdout);
  352.                     free(str);
  353.                     return -1;
  354.                 }
  355.             }
  356.         }
  357.         check_time();
  358.         if(ar.state != TIMER_RUN) {
  359.             free(str);
  360.             if(debug) printf("%s",str);fflush(stdout);
  361.             return -1;
  362.         }
  363.     }
  364.     if(debug) printf("%s",str);fflush(stdout);
  365.     free(str);
  366.     return 1;
  367. } /* m_expect */
  368.  
  369. int modem_init(dev, argc, argv)
  370. unsigned dev;
  371. int argc;
  372. char **argv;
  373. {
  374.     int i;
  375.     i=0;
  376.     debug = 0;
  377.     if(argv[0][0]=='-') {
  378.         debug=1;
  379.         i++;
  380.         argc--;
  381.     }
  382.     while(argc) {
  383.         if(debug) {
  384.             printf("\nI'm sending  : '%s'\n",argv[i]);
  385.             fflush(stdout);
  386.         }
  387.         if(debug && argc>1) {
  388.             printf("I'm expecting: '%s'\n",argv[1+i]);
  389.             fflush(stdout);
  390.         }
  391.         if(m_send(dev,argv[i++]) == -1) return -1;
  392.         if(--argc>0) {
  393.             if(m_expect(dev,argv[i++]) == -1) return -1;
  394.             argc--;
  395.         }
  396.     }
  397.     return 1;
  398. } /* modem_init */
  399. #endif /* MODEM_CALL */
  400.